package com.pulse.base.task;

import com.alibaba.fastjson2.JSON;
import com.pulse.base.domain.Alarm;
import com.pulse.base.domain.CircuitThreshold;
import com.pulse.base.domain.Device;
import com.pulse.base.domain.JobDispatch;
import com.pulse.base.service.IAlarmService;
import com.pulse.base.service.ICircuitThresholdService;
import com.pulse.base.service.IDeviceService;
import com.pulse.base.service.IJobDispatchService;
import com.pulse.common.core.redis.RedisCache;
import com.pulse.common.exception.ServiceException;
import com.pulse.common.exception.job.TaskException;
import com.pulse.common.utils.DateUtils;
import com.pulse.common.utils.SecurityUtils;
import com.pulse.mqtt.MqttConsumer;
import com.pulse.quartz.domain.SysJob;
import com.pulse.quartz.service.ISysJobService;
import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * @ClassName DeviceTask
 * @Description
 * @Author 陆帅
 * @Date 2024/9/12 15:49
 */
@Component("deviceTask")
public class DeviceTask {

    private static final Logger log = LoggerFactory.getLogger(DeviceTask.class);

    @Autowired
    private IDeviceService deviceService;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private ISysJobService sysJobService;
    @Autowired
    private IJobDispatchService jobDispatchService;
    @Autowired
    private IAlarmService alarmService;
    @Autowired
    private ICircuitThresholdService circuitThresholdService;

    public void deviceStatusMonitoring(){
        try{
            List<Device> devices = deviceService.selectAllDeviceList();
            for (Device device : devices) {
                Object deviceHeartbeat = redisCache.getCacheObject("Heartbeat:" + device.getDeviceNo());
                // 如果未收到心跳信息并且设备状态为连接状态，修改设备状态为断开
                if(deviceHeartbeat == null && "connected".equals(device.getStatus())){
                    deviceService.updateDeviceStatus(device.getDeviceId(),"disConnected");

                    // 创建报警记录 发布报警
                    Date alarmTime = DateUtils.getNowDate();
                    Alarm alarm = new Alarm();
                    alarm.setDeviceNo(device.getDeviceNo());
                    alarm.setAlarmType(1);
                    alarm.setLevel(1);
                    alarm.setCreateTime(alarmTime);
                    alarm.setCreateBy("task");
                    alarm.setType("网络中断报警");
                    String description = "【网络中断报警】"+DateUtils.dateTimeNow("yyyy年MM月dd日HH时mm分ss秒")+"，监测系统发现编号["+device.getDeviceNo()+"]的设备已超时未接收到心跳信号，疑似发生网络连接中断。请及时检查设备状态及网络连接。";
                    alarm.setDescription(description);
                    alarmService.insertAlarm(alarm);
                    // 发布
                    String jsonString = JSON.toJSONString(alarm);
                    MqttConsumer.publish("$FAMS/OTU/"+alarm.getDeviceNo()+"/alarm", jsonString);
                }
                else if(deviceHeartbeat != null && "disConnected".equals(device.getStatus())){
                    deviceService.updateDeviceStatus(device.getDeviceId(),"connected");
                }
            }
        }
        catch (Exception e){
            log.error("设备状态监测发生异常："+e.getMessage());
        }
    }

    public void deviceChannelNumMonitoring(){
        try{
            while (true){
                String data = redisCache.pop("DeviceChannelNum");
                if(data == null || data.isEmpty()){  // 如果消息队列中无数据
                    return;
                }
                String[] dcn = data.split(":");
                if(dcn.length!=2) continue;
                String deviceNo = dcn[0];
                Long channelNum = Long.parseLong(dcn[1]);
                Device device = deviceService.selectDeviceByDeviceNo(deviceNo);
                if(device==null) continue;

                // 如果通道数相同，不进行处理
                if(device.getChannelNum().equals(channelNum)) continue;

                // 如果是新设备，添加通道
                if(device.getChannelNum() < channelNum){ // 如果通道变多，添加通道任务
                    addChannelJob(device,channelNum);
                }else{ // 如果通道变少，通道数量报警
                    // 创建报警记录 发布报警
                    Date alarmTime = DateUtils.getNowDate();
                    Alarm alarm = new Alarm();
                    alarm.setDeviceNo(device.getDeviceNo());
                    alarm.setAlarmType(1);
                    alarm.setLevel(1);
                    alarm.setCreateTime(alarmTime);
                    alarm.setCreateBy("task");
                    alarm.setType("端口减少报警");
                    String description = "【端口减少报警】"+DateUtils.dateTimeNow("yyyy年MM月dd日HH时mm分ss秒")+"，监测系统发现编号["
                            +device.getDeviceNo()+"]的设备端口数量由"+device.getChannelNum()+"减少到"+channelNum+"，疑似发生设备故障。请及时检查设备状态。";
                    alarm.setDescription(description);
                    alarmService.insertAlarm(alarm);
                    // 发布
                    String jsonString = JSON.toJSONString(alarm);
                    MqttConsumer.publish("$FAMS/OTU/"+alarm.getDeviceNo()+"/alarm", jsonString);
                }
            }
        }catch (Exception e){
            log.error("设备通道监测发生异常:"+e.getMessage());
        }
    }

    /**
     * 添加设备通道和通道任务
     * @param device
     * @param channelNum
     * @throws SchedulerException
     * @throws TaskException
     */
    @Transactional
    public void addChannelJob(Device device, Long channelNum) throws SchedulerException, TaskException {
        // 添加通道
        for(int i =0 ;i < channelNum;i++){
            JobDispatch jobDispatch = jobDispatchService.selectByDeviceNoAndChannel(device.getDeviceNo(),channelNum+1);
            if(jobDispatch!=null){
                continue;
            }
            // 将任务插入到数据库
            SysJob sysJob = new SysJob();
            sysJob.setJobName("光路测试"+device.getDeviceNo()+"-"+(i+1));
            sysJob.setJobGroup("MEASURE");
            sysJob.setInvokeTarget("measureTestTask.periodicTesting('"+device.getDeviceNo()+"',"+(i+1)+")");
            sysJob.setMisfirePolicy("3");
            sysJob.setConcurrent("1");
            sysJob.setStatus("1");
            sysJob.setCronExpression("0 0 0 1/1 * ?");
            sysJob.setCreateBy("task");
            sysJob.setCreateTime(DateUtils.getNowDate());
            int resJob = sysJobService.insertJob(sysJob);  // 添加定时任务
            if(resJob <= 0){
                throw new ServiceException("添加调度任务失败");
            }
            // 插入数据到任务调度表
            jobDispatch = new JobDispatch();
            jobDispatch.setName(sysJob.getJobName());
            jobDispatch.setJobId(sysJob.getJobId());
            jobDispatch.setDeviceNo(device.getDeviceNo());
            jobDispatch.setChannel(i+1L);
            resJob = jobDispatchService.insertJobDispatch(jobDispatch);
            if(resJob <= 0){
                throw new ServiceException("添加调度任务失败");
            }

            // 创建circuitThreshold
            CircuitThreshold circuitThreshold = circuitThresholdService.selectThresholdByDeviceNoAndChannel(device.getDeviceNo(), i + 1);
            if(circuitThreshold == null){
                circuitThreshold = new CircuitThreshold();
                circuitThreshold.setDeviceNo(device.getDeviceNo());
                circuitThreshold.setChannel(i+1);
                circuitThreshold.setFullLengthThreshold(100d);
                circuitThreshold.setFullAttenThreshold(5d);
                circuitThresholdService.insertThreshold(circuitThreshold);
            }
        }

        device.setChannelNum(channelNum);
        deviceService.updateDevice(device);
    }
}
